package com.matt.service.impl;

import com.matt.commons.exception.BusinessException;
import com.matt.controller.po.ProductPO;
import com.matt.domain.Product;
import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.query.ProductQuery;
import com.matt.foundation.utils.CopyUtils;
import com.matt.foundation.vo.ProductTypeVo;
import com.matt.repository.ProductRepository;
import com.matt.repository.base.ProductNativeRepository;
import com.matt.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * ***************
 * Created by Ron
 * from com.matt
 * on 2018/6/13 0013.
 * ***************
 */
@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private ProductNativeRepository productNativeRepository;

    @Override
    public Page<Product> getPages(ProductQuery query, Pageable pageable) {
        String areaId = query.getAreaId();
        Specification<Product> specification = new Specification<Product>() {

            @Override
            public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.and(cb.equal(root.get("isVisible"), 1)));
                predicates.add(cb.and(cb.equal(root.get("deleted"), 0)));
                predicates.add(cb.and(cb.equal(root.get("areaId"), areaId)));
                query.where(predicates.toArray(new Predicate[predicates.size()]));
                query.orderBy(cb.desc(root.get("created")));
                return query.getRestriction();
            }
        };
        Page<Product> productPage = productRepository.findAll(specification, pageable);
        return productPage;
    }

    @Override
    public Product findByName(String name, String areaId) {
        return productRepository.findByNameAndAreaIdAndDeletedIsFalse(name,areaId);
    }

    @Override
    public Product add(String staffId, ProductPO param) {
        Product product = productRepository.findByNameAndAreaIdAndDeletedIsFalse(param.getName(), param.getAreaId());

        if (!Objects.isNull(product)){
            if(product.getDeleted()){
                product.setDeleted(false);
                product.setIsVisible(1);
                productRepository.save(product);
                return product;
            }else{
                throw new BusinessException(ErrorCode.PRODUCT_IS_SAME, "该产品已经存在，不能再新增！");
            }

        }

        Product vo = new Product();

//        BeanUtils.copyProperties(param, vo);
        CopyUtils.copyProperties(param, vo);

        return productRepository.save(vo);
    }

    @Override
    public Product update(String staffId, ProductPO param) {

        Product vo = findOne(param.getId(), param.getAreaId());

        if (Objects.isNull(vo))
            throw new BusinessException(ErrorCode.PRODUCT_NOT_EXIST, "该产品不存在！");

        Product nameCheckder = productRepository.findByNameAndAreaIdAndIdNotAndDeletedIsFalse(param.getName(), param.getAreaId(), vo.getId());
        if (!Objects.isNull(nameCheckder)){
            throw new BusinessException(ErrorCode.PRODUCT_IS_SAME, "该产品已经存在,不能重复！");
        }

//        BeanUtils.copyProperties(params, vo);
        CopyUtils.copyPropertiesSkipNullAndExternalProperties(param, vo, new String[]{
                "id", "areaId"
        });

//        vo.setCode(code);
//        vo.setName(name);
//        vo.setIsVisible(isVisible);
//        vo.setType(type);
//        vo.setStandardAmount(standardAmount);
//        vo.setUnit(unit);

        return productRepository.save(vo);
    }

    @Override
    public Product update(Product product){
        return productRepository.save(product);
    }

    @Override
    public boolean delete(String id,String areaId) {
        Product vo = productRepository.findByIdAndAreaId(id, areaId);
        if (Objects.isNull(vo))
            throw new BusinessException(ErrorCode.PRODUCT_NOT_EXIST, "该产品不存在！");
        vo.setDeleted(true);
        vo.setIsVisible(0);
        productRepository.save(vo);

        return true;
    }

    @Override
    public List<ProductTypeVo> getTypeByAreaId(String areaId) {
        return productNativeRepository.getTypeByAreaId(areaId);
    }

    @Override
    public Product findOne(String id, String areaId) {
        return productRepository.findByIdAndAreaIdAndDeletedIsFalse(id, areaId);
    }

    @Override
    public Product findById(String id) {
        return productRepository.findByIdAndDeletedIsFalse(id);
    }

    @Override
    public List<Product> findAllByIds(String areaId, List<String> ids){
        return productRepository.findAllByAreaIdAndIdInAndIsVisibleOrderByCreatedDesc(areaId, ids, 1);
    }

    @Override
    public Product findByNameAndAreaId(String name, String areaId) {
         return productRepository.findByIdAndAreaIdAndDeletedIsFalse(name,areaId);
    }
}
